package com.wzl.base;

import com.wzl.base.domain.Student;

/**基本数据类型 & String
 * 温故而知新(╯︵╰)
 * Java学习
 * 对于基本类型，== 判断两个值是否相等，基本类型没有 equals() 方法。
 * 对于引用类型，== 判断两个变量是否引用同一个对象，而 equals() 判断引用的对象是否等价。
 * @author weiZhiLin
 * @version 1.0
 * @date 2020/1/17 10:29
 */
public class StudyDemo01 {
    // 自动装箱与拆箱
    Integer x = 2;     // 装箱 调用了 Integer.valueOf(2)
    int y = x;         // 拆箱 调用了 X.intValue()


    // 缓存池
    // 基本类型对应的缓冲池如下：
    //
    // boolean values true and false
    // all byte values
    // short values between -128 and 127
    // int values between -128 and 127
    // char in the range \u0000 to \u007F

    // new Integer(123) 每次都会新建一个对象；
    // Integer.valueOf(123) 会使用缓存池中的对象，多次调用会取得同一个对象的引用。
    public static void cachePool() {
        System.out.println("---------cachePool-----------");
        Integer x = new Integer(123);
        Integer y = new Integer(123);
        System.out.println(x == y); // false

        Integer z = Integer.valueOf(127); // 范围在 -128 and 127 才会在缓存池中，Integer 缓存池比较特殊，128 这个上界是可调的，在启动 jvm 的时候，通过 -XX:AutoBoxCacheMax=<size> 来指定这个缓冲池的大小
        Integer k = Integer.valueOf(127);
        System.out.println(z == k); // true

        // 编译器会在自动装箱过程调用 valueOf() 方法
        Integer m = 123;
        Integer n = 123;
        System.out.println(m == n); // true

        Student student = new Student();
        System.out.println(student.getBirthday()); // null Integer 默认是 null
        System.out.println(student.getIntBirthday());// 0 int 默认是 0
    }

    /*
    Java 8 中 String 使用 char[] 存储
    Java 9 中 String 使用 byte[] 存储，同时使用 coder 来标识使用了哪种编码。

    String value 数组被声明为 final，这意味着 value 数组初始化之后就不能再引用其它数组。
    并且 String 内部没有改变 value 数组的方法，因此可以保证 String 不可变。

    不可变的好处:
    - 可以缓存 hash 值
        因为 String 的 hash 值经常被使用，例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变，因此只需要进行一次计算。
    - String Pool 的需要
        如果一个 String 对象已经被创建过了，那么就会从 String Pool 中取得引用。只有 String 是不可变的，才可能使用 String Pool。
    - 安全性
        String 经常作为参数，String 不可变性可以保证参数不可变。例如在作为网络连接参数的情况下如果 String 是可变的，那么在网络连接过程中，String 被改变，改变 String 的那一方以为现在连接的是其它主机，而实际情况却不一定是。
    - 线程安全
        String 不可变性天生具备线程安全，可以在多个线程中安全地使用。

    StringBuffer 和 StringBuilder 是可变的
    StringBuffer 是线程安全的，内部使用 synchronized 进行同步
    StringBuilder 不是线程安全的
     */
    String str = "测试";

    public static void stringPool() {
        System.out.println("---------stringPool-----------");
        String str01 = new String("hello");
        String str02 = new String("hello");
        System.out.println(str01 == str02); // false

        // 这种字面量的形式创建字符串，会自动地将字符串放入 String Pool 中。
        String str03 = "hello";
        String str04 = "hello";
        System.out.println(str03 == str04); // true

        String str05 = str01.intern(); // 使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool
        String str06 = "hello";
        System.out.println(str05 == str06); // true

        // 使用这种方式一共会创建两个字符串对象（前提是 String Pool 中还没有 "eatboooo" 字符串对象）。
        // "eatboooo" 属于字符串字面量，因此编译时期会在 String Pool 中创建一个字符串对象，指向这个 "eatboooo" 字符串字面量；
        // 而使用 new 的方式会在堆中创建一个字符串对象。
        String eatboooo = new String("eatboooo");

    }

    public static void main(String[] args) {
        // cachePool
//        cachePool();
        // stringPool
        stringPool();
    }
}
